package com.envper.common.service.impl;

import com.envper.common.domain.dto.UserDto;
import com.envper.common.service.FileService;
import com.envper.common.service.RoleService;
import com.mybatisflex.core.query.QueryWrapper;
import com.envper.mysql.base.service.RoleBaseService;
import com.envper.mysql.base.service.UserBaseService;
import com.envper.mysql.base.service.UserRoleBaseService;
import com.envper.mysql.domain.Status;
import com.envper.mysql.domain.entity.TUser;
import com.envper.mysql.domain.vo.UserVo;
import com.envper.common.exception.GlobalException;
import com.envper.common.mapper.UserMapper;
import com.envper.common.util.PasswordUtils;
import com.envper.common.service.UserService;
import com.envper.common.util.IdUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Set;

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {
    private final UserBaseService userBaseService;
    private final UserRoleBaseService userRoleBaseService;
    private final RoleBaseService roleBaseService;
    private final RoleService roleService;
    private final IdUtils idUtils;
    private final FileService fileService;

    @Override
    public UserDto getUserDtoByUsername(String username) {
        TUser tUser = userBaseService.getOne(new QueryWrapper().eq("username", username));
        UserDto userDto = UserMapper.INSTANCE.toUserDto(tUser);
        userDto.setRoleCode("NULL");
        boolean exists = userRoleBaseService.exists(new QueryWrapper().eq("user_id", tUser.getId()));
        if (exists){
            Long roleId = userRoleBaseService.getOne(new QueryWrapper().eq("user_id",tUser.getId())).getRoleId();
            userDto.setRoleCode(roleBaseService.getById(roleId).getCode()); ;
        }
        return userDto;
    }

    @Override
    public UserDto getUserInfoById(Long userId) {
        if (ObjectUtils.isEmpty(userId)) throw new GlobalException(Status.USERIDNOTFOUND);
        TUser tUser = userBaseService.getById(userId);
        UserDto userDto = UserMapper.INSTANCE.toUserDto(tUser);
        userDto.setRoleCode("NULL");
        boolean exists = userRoleBaseService.exists(new QueryWrapper().eq("user_id", userId));
        if (exists){
            Long roleId = userRoleBaseService.getOne(new QueryWrapper().eq("user_id",userId)).getRoleId();
            userDto.setRoleCode(roleBaseService.getById(roleId).getCode()); ;
        }
        return userDto;
    }

    @Override
    public UserVo getUserVoById(Long userId) {
        if (ObjectUtils.isEmpty(userId)) throw new GlobalException(Status.USERIDNOTFOUND);
        TUser tUser = userBaseService.getById(userId);
        return UserMapper.INSTANCE.toUserVo(tUser);
    }

    @Override
    public List<UserVo> getUserList() {
        List<TUser> tUserList = userBaseService.list();
        return UserMapper.INSTANCE.toUserVoList(tUserList);
    }

    @Override
    public List<UserVo> getUserListBySleep() {
        List<TUser> tUserList = userBaseService.list();
        return UserMapper.INSTANCE.toUserVoList(tUserList);
    }

    @Override
    public List<UserVo> searchUserList(String keyword) {
        Long userId = idUtils.getUserIdByRequest();
        QueryWrapper queryWrapper = new QueryWrapper().notIn("id", userId);
        if (StringUtils.hasText(keyword)) {
            queryWrapper.like("nickname", keyword);
        }
        List<TUser> tUserList = userBaseService.list(queryWrapper);
        return UserMapper.INSTANCE.toUserVoList(tUserList);
    }

    @Override
    public List<UserDto> getUserInfoList() {
        List<TUser> tUserList = userBaseService.list();
        List<UserDto> userDtoList = UserMapper.INSTANCE.toUserDtoList(tUserList);
        if (CollectionUtils.isEmpty(userDtoList)) return List.of();
        userDtoList.forEach(item -> {
            List<String> roleCodeListByUserId = roleService.getRoleCodeListByUserId(item.getId());
            item.setRoleCode(roleCodeListByUserId.get(0));
        });
        return userDtoList;
    }

    @Override
    @Transactional
    public void deleteUserByUserId(Long userId) {
        userBaseService.removeById(userId);
    }

    @Override
    public void editUserPasswordByUserId(UserDto userDto) {
        TUser tUser = UserMapper.INSTANCE.toTUser(userDto);
        String encodePassword = PasswordUtils.encode(userDto.getPassword());
        tUser.setPassword(encodePassword);
        userBaseService.updateById(tUser);
    }

    @Override
    public void editUserInfoByUserId(UserDto userDto) {
        TUser tUser = UserMapper.INSTANCE.toTUser(userDto);
        userBaseService.updateById(tUser);
    }

    @Override
    public void uploadAvatar(MultipartFile avatar) {
        Long userId = idUtils.getUserIdByRequest();
        String url = fileService.uploadAvatar(avatar, userId);
        userBaseService.updateById(TUser.builder().id(userId).avatar(url).build());
    }
}
